package com.epic.services;

import com.epic.dao.assetmgr.AssetInfoMapper;
import com.epic.inter.IJobManager;
import com.epic.po.assetmgr.AssetInfo;
import com.epic.po.assetmgr.AssetInfoExample;
import com.epic.po.quartz.TaskInfo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//@Service
@Component("AssetListener")
public class AssetsListener implements ApplicationListener<ContextRefreshedEvent> {
    private static Logger logger =  LoggerFactory.getLogger(AssetsListener.class);

    @Autowired
    private AssetInfoMapper assetInfoMapper;

    @DubboReference(check = false)
    private IJobManager iJobManager;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
//        logger.info("partent " + contextRefreshedEvent.getApplicationContext().getParent());
        logger.info("asset start");
        AssetInfoExample assetInfoExample = new AssetInfoExample();
        List<AssetInfo> assetInfoArrayList = assetInfoMapper.selectByExample(assetInfoExample);
        for (int i = 0; i < assetInfoArrayList.size(); i++) {
            logger.info(assetInfoArrayList.get(i).getId().toString());
        }
        /*
        try{
            String URL = "jdbc:postgresql://10.65.133.122:5432/pger";
            String user = "pger";
            String passwd = "12345";
            Class.forName("org.postgresql.Driver");
            Connection connection = DriverManager.getConnection(URL,user,passwd);
            String sql = "select * from tbl_asset_info";
            PreparedStatement statement = connection.prepareStatement(sql);
            ResultSet rs = statement.executeQuery();
            while (rs.next()){
                logger.info(rs.getString("id"));
            }
            statement.close();
            connection.close();

        }catch (Exception e){
            logger.error(e.getMessage());
        }
        TaskInfo taskInfo = new TaskInfo();
        taskInfo.setRunArgs("11");
        taskInfo.setTaskId("11");
        taskInfo.setTaskBean("CleanTask");
        taskInfo.setRunMode(1);
         */
//        taskInfo.setScheduleParam("* */2 * * * ? *");
//        taskInfo.setTaskDesc("AsssetTask");
//        taskInfo.setTaskUser(1);
//        try{
//            iJobManager.addJob(taskInfo);
//
//        }catch (Exception e){
//            logger.error(e.getMessage());
//        }
        TaskInfo taskInfo = new TaskInfo();
        taskInfo.setRunArgs("22");
        taskInfo.setTaskId("22");
        taskInfo.setTaskBean("AssetTask");
        taskInfo.setRunMode(1);
        taskInfo.setScheduleParam("0 /10 * * * ? *");
        taskInfo.setTaskDesc("AssetTask");
        taskInfo.setTaskUser(1);
        try{
            iJobManager.addJob(taskInfo);
//            iJobManager.test();
            logger.info("test task add paass ");
        }catch (Exception e){
            logger.error(e.getMessage());
        }
        logger.info("asset end");
    }
}
/**
 *
 * 在早期，组件要从Spring事件获知自定义域事件中获取通知，那么组件必须实现ApplicationListener接口并覆写onApplicationEvent方法。
 * 但是它会针对每一个事件都创建一个新类，从而造成代码瓶颈
 * ContextRefreshedEvent
 *
 * 在spring项目经常遇到@PostConstruct注解
 * 这个注解是在javax.annotation包下的，也就是java拓展包定义的注解，并不是spring定义的，但至于为什么不在java包下，
 * 是因为java语言的元老们认为这个东西并不是java核心需要的工具，因此就放到扩展包里
 *  被注解的方法，在对象加载完依赖注入后执行。
 *     <!-- 自动扫描dao和service包(自动注入) -->
 *     <context:component-scan base-package="com.epic" />
 *
 *     主要是搞成注解不用配置
 *
 *   在IOC的容器的启动过程，当所有的bean都已经处理完成之后，spring ioc容器会有一个发布事件的动作。从 AbstractApplicationContext 的源码中就可以看出
 * 当ioc容器加载处理完相应的bean之后，也给我们提供了一个机会（先有InitializingBean，后有ApplicationListener<ContextRefreshedEvent>），可以去做一些自己想做的事。其实这也就是spring ioc容器给提供的一个扩展的地方。我们可以这样使用这个扩展机制。
 *
 * 执行两次 操作
 *
 * Spring的@PostConstruct注解在方法上，表示此方法是在Spring实例化该Bean之后马上执行此方法，之后才会去实例化其他Bean，并且一个Bean中@PostConstruct注解的方法可以有多个。
 *
 * 解决onApplicationEvent(方法被执行两次以上的问题
 *
 * 原因：无论是使用spring还是spring mvc，系统会存在两个容器，一个是root application context ，另一个就是projectName-servletContext（作为root application context的子容器）。这种情况下，就会造成onApplicationEvent方法被执行两次。
 * 解决方法：如代码所示，用个标志标记是否已执行
 * 主要原因是初始化root容器之后，会初始化project-servlet.xml对应的子容器。我们需要的是只执行一遍即可
 logger.info("partent " + contextRefreshedEvent.getApplicationContext().getParent()); 判断是否为空 如果等于空就执行 如果容器的父容器为空，那么他就是Root容器。
 *
 * 我没遇到
 *
 *
 * classpath 和 classpath* 区别：
 * classpath：只会到你指定的class路径中查找找文件;
 * classpath*：不仅包含class路径，还包括jar文件中(class路径)进行查找.
 *
 * 举个简单的例子，在我的web.xml中是这么定义的：classpath*:META-INF/spring/application-context.xml
 * 那么在META-INF/spring这个文件夹底下的所有application-context.xml都会被加载到上下文中，这些包括META-INF/spring文件夹底下的 application-context.xml，META-INF/spring的子文件夹的application-context.xml以及jar中的application-context.xml。
 *
 * 如果我在web.xml中定义的是：classpath:META-INF/spring/application-context.xml
 * 那么只有META-INF/spring底下的application-context.xml会被加载到上下文中。
 */
